package com.hd.platform.util.image;


import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;

/**
 * Created by qingshengzheng on 17/5/5.
 */
public class PhashIndex {

    private static PhashIndex phashIndex;

    private static class Entry<E> {
        E e;
        Entry<E> nextEntry;

        public Entry(E e, Entry<E> nextEntry) {
            this.e = e;
            this.nextEntry = nextEntry;
        }

        public E get() {
            return e;
        }

    }

    public List<ImgNode> getDisImgNode(Entry<ImgNode> first, int n) {
        List<ImgNode> result = new ArrayList<ImgNode>();
        int i = 0;
        while (first.nextEntry != null) {
            Entry<ImgNode> node = first.nextEntry;
            result.add(node.get());
            i++;
            if (i >= n)
                break;

        }
        return result;
    }

    public int add(ImgNode node) {
        return 0;
    }

    public int add(Entry<ImgNode> first, ImgNode node, int len, int maxsize) {
        int clen;
        Entry<ImgNode> tempfirst = first;
        if (tempfirst.nextEntry == null) {
            first.nextEntry = new Entry<ImgNode>(node, null);
            clen = 1;
            return clen;
        }

        while (tempfirst.nextEntry != null) {
            Entry<ImgNode> entry = tempfirst.nextEntry;
            ImgNode tmp = entry.get();
            if (node.getDis() < tmp.getDis()) {
                Entry aa = new Entry<ImgNode>(node, tempfirst.nextEntry);
                tempfirst.nextEntry = aa;
                clen = len + 1;
                return clen;
            }
        }
        //超过固定阈值,清理
        if (len - maxsize > 20) {
            int i = 0;
            Entry<ImgNode> t = tempfirst;
            while (i < len) {
                t = tempfirst.nextEntry;
                i++;
            }
            t.nextEntry = null;
        }

        return 0;
    }


    private ImagePHash imagePHash;
    private Map<String, Set<ImgNode>> indexs = new HashMap<String, Set<ImgNode>>();

    // 这里假设都是小文件
    public void addFile(String fileName, ImgNode imgNode) {
        String[] words = getSubHash(imgNode.getPhash());
        for (int i = 0; i < words.length; i++) {
            String word = words[i];
            Set<ImgNode> wordIndex = indexs.get(word);
            if (wordIndex == null) {
                wordIndex = new HashSet<ImgNode>();
                indexs.put(word, wordIndex);
            }
            wordIndex.add(imgNode);
        }
    }

    public String[] getSubHash(String phash) {
        String[] temp = new String[4];
        if (phash.length() != ImagePHash.size)
            return null;
        temp[0] = phash.substring(0, 4);
        temp[1] = phash.substring(4, 8);
        temp[2] = phash.substring(8, 12);
        temp[3] = phash.substring(12, 16);
        return temp;

    }


    /**
     * 根据某个key获取对应的
     *
     * @param keyword
     * @return
     */
    public Set<ImgNode> search(String keyword) {
        String[] subkeys = getSubHash(keyword);
        Set<ImgNode> results = indexs.get(subkeys[0]);
        results.addAll(indexs.get(subkeys[1]));
        results.addAll(indexs.get(subkeys[2]));
        results.addAll(indexs.get(subkeys[3]));
        return new HashSet<ImgNode>(results);
    }


    /**
     * 根据phash获取最相近的图片文件
     *
     * @param phash
     * @param n
     * @return
     */
    public List<ImgNode> searchFileByphash(String phash, int n) {
        List result = new ArrayList();
        String[] subphash = getSubHash(phash);
        Set<ImgNode> nodes = search(phash);
        Entry<ImgNode> fist = new Entry<>(null, null);
        int len = 0;
        for (Iterator it = nodes.iterator(); it.hasNext(); ) {
            ImgNode node = (ImgNode) it.next();
            int dis = imagePHash.distance(phash, node.getPhash());
            node.setDis(dis);
            len = add(fist, node, len, n);
        }

        return getDisImgNode(fist, n);

    }


    public static void main(String[] args) throws Exception {
      /*  PhashIndex test = new PhashIndex();
        test.addFile("file1", "hello fuck world todotodo");
        test.addFile("file2", "go to get it if you want it");
        test.addFile("C:/data/hello.txt");*/
     /*   System.out.println(test.search("it"));
        System.out.println(test.search("you"));
        System.out.println(test.search("vonzhou"));*/
    }
}
